#include "stdafx.h"
#include <Thunk/ThunkBase.h>
#include <assert.h>


#include <windows.h>


namespace Thunk
{
	void Helper::SetTransferDST(dword_ptr src,dword dst)
	{
		byte *op = const_cast<byte*>( static_cast<const byte*>(src) );
		
		switch(*op++)
		{
		case 0xE8:	//CALL offset(dword)
		case 0xE9:	//JMP offset(dword)
			{
				dword *offset = reinterpret_cast<dword*>(op);
				*offset = dst - ( PointerToInt32(src)+sizeof(*op)+sizeof(dword) );
			}
			break;
		case 0xEB:	//JMP offset(byte)
			{
				// int8_t uint8_t?
				byte *offset = op;
				*offset = static_cast<byte>(
					dst - ( PointerToInt32(src)+sizeof(*op)+sizeof(byte) )
					);
			}
		    break;
		default:
			assert(!"not complete");
		    break;
		}
	}

	dword Helper::GetTransferDST(dword_ptr src)
	{
		const byte *op =static_cast<const byte*>(src);
		switch(*op++)
		{
		case 0xE8:	//CALL offset(dword)
		case 0xE9:	//JMP offset(dword)
			{
				const dword *offset = reinterpret_cast<const dword*>(op);
				return *offset + PointerToInt32(src)+sizeof(*op)+sizeof(dword);
			}
			break;
		case 0xEB:	//JMP offset(byte)
			{
				const byte *offset = op;
				return *offset + PointerToInt32(src)+sizeof(*op)+sizeof(byte);
			}
			break;
		default:
			assert(!"not complete");
			break;
		}
		return 0;
	}

	void Helper::FlushInstructionCache(const void*Instructions,unsigned long size)
	{
		::FlushInstructionCache(GetCurrentProcess(),Instructions,size);
	}

	void Helper::ReviseVirtualProtect(void*Address,unsigned long size)
	{
		DWORD old;
		VirtualProtectEx(GetCurrentProcess(), Address,size, PAGE_EXECUTE_READWRITE, &old);
	}

}
